/*
 * Copyright 2008-2009 Aying.Net with Fuchun.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.aying.util;

import java.util.Map;
import java.util.Iterator;
import java.util.Collection;
import java.util.Enumeration;
import java.lang.reflect.Array;

import net.aying.resources.Resources;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 包含基本 <code>Java</code> 类型基本操作常用方法的便捷工具类。
 * 
 * @author Fuchun
 * @version 1.0, 2009-6-9
 */
public class Utils {

    /** 隐藏构造方法，不允许构造 <code>Utils</code>类。 */
    Utils() {}

    @SuppressWarnings("unused")
    private static final Log log = LogFactory.getLog(Utils.class);

    /**
     * 检测给定的对象是否<strong>为空</strong>。
     * <p>
     * <strong>object</strong> 类型列表：
     * </p>
     * <ul>
     * <li>java.util.Collection --&gt; 为null或者长度为 0 时，返回 <code>true</code>，否则<code>false</code>。</li>
     * <li>java.util.Iterator --&gt; 为null或者无下一个元素时，返回 <code>true</code>，否则<code>false</code>。</li>
     * <li>java.util.Map --&gt; 为null或者大小为 0 时，返回 <code>true</code>，否则<code>false</code>。</li>
     * <li>java.lang.String --&gt; 为null或者为空字符串时，返回 <code>true</code>，否则<code>false</code>。</li>
     * <li>java.util.Enumeration --&gt; 为null或者无下一个元素时，返回 <code>true</code>，否则<code>false</code>。</li>
     * <li>java.lang.Array --gt; 为null或者长度为 0 时，返回 <code>true</code>，否则<code>false</code>。</li>
     * </ul>
     * 
     * @param object 要检测的对象。
     * @return 若检测的对象为空(值)，返回 <code>true</code>，否则<code>false</code>。
     */
    @SuppressWarnings("unchecked")
    public static boolean isEmpty(Object object) {
        if (object == null) return true;
        if (object instanceof String) return "".equals((String) object);
        if (object instanceof Collection) return ((Collection) object).size() == 0;
        if (object instanceof Map) return ((Map) object).size() == 0;
        if (object instanceof Iterator) return !((Iterator) object).hasNext();
        if (object instanceof Enumeration) return !((Enumeration) object).hasMoreElements();
        try {
            return Array.getLength(object) == 0;
        } catch (IllegalArgumentException e) {
            return true;
        }
    }

    /**
     * 检测给定的对象是否<strong>不为空</strong>。具体见 {@link #isEmpty(Object)}
     * 
     * @param object 要检测的对象。
     * @return 若检测的对象不为空(值)，返回 <code>true</code>，否则<code>false</code>。
     * @see #isEmpty(Object)
     */
    public static boolean isNotEmpty(Object object) {
        return !isEmpty(object);
    }

    /**
     * 返回给定对象的长度。
     * 
     * @param object 要计算长度的对象。
     * @return 给定字符串的字节长度。
     */
    @SuppressWarnings("unchecked")
    public static Integer getLength(Object object) {
        if (object == null) return 0;
        if (object instanceof String) return ((String) object).length();
        if (object instanceof Collection) return ((Collection) object).size();
        if (object instanceof Map) return ((Map) object).size();
        int count = 0;
        if (object instanceof Iterator) {
            Iterator it = (Iterator) object;
            while (it.hasNext()) {
                count++;
                it.next();
            }
            return count;
        }
        if (object instanceof Enumeration) {
            Enumeration enum_ = (Enumeration) object;
            while (enum_.hasMoreElements()) {
                count++;
                enum_.nextElement();
            }
            return count;
        }
        try {
            count = Array.getLength(object);
            return count;
        } catch (IllegalArgumentException ex) {
            log.warn(Resources.getMessage(Resources.UTIL_WARN_GETLENGTH, "object"));
            return 0;
        }
    }
}
